package org.andao.security.service.impl;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Random;

import org.andao.core.base.service.BaseServiceImpl;
import org.andao.core.cache.EhCacheManager;
import org.andao.core.dao.helper.HibernateHelper;
import org.andao.core.dao.helper.Page;
import org.andao.core.dao.jdbc.JdbcSupportDao;
import org.andao.core.exception.ServiceException;
import org.andao.core.utils.ExStringUtils;
import org.andao.security.cache.CacheSecManager;
import org.andao.security.model.OrgUnit;
import org.andao.security.service.OrgUnitService;
import org.apache.commons.lang.StringUtils;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.Restrictions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;



/**
 * 组织单位服务实现. 
 * 
 * @author Marco.hu(hzg139@163.com)
 */
@Service("orgUnitService")
@Transactional
public class OrgUnitServiceImpl extends BaseServiceImpl<OrgUnit> implements OrgUnitService{
	
	@Autowired 
	@Qualifier("defaultJdbcSupportDao")	
	private JdbcSupportDao jdbcDao;//注入jdbc template 支持

	//新增
	public void addOrgUnit(OrgUnit orgUnit) throws ServiceException {
		exGeneralHibernateDao.save(orgUnit);
		//插入缓存
		addOrgUnitToCache(orgUnit);
	}

	//更新
	public void updateOrgUnit(OrgUnit orgUnit) throws ServiceException {
		OrgUnit o = get(orgUnit.getResourceid());
		
		OrgUnit p = get(o.getParent().getResourceid());
		this.flush();
		
		exGeneralHibernateDao.update(orgUnit);
		updateOrgUnitToCache(orgUnit);
	}

		
	@Override
	public void delete(Serializable id) throws ServiceException {		
		OrgUnit orgUnit = get(id);
		orgUnit.setUnitCode(orgUnit.getUnitCode()+"_DEL"+new Random().nextInt(9999));
		save(orgUnit);
		super.delete(id);
		removeOrgUnitFromCache(id);
	}

	public void batchCascadeDelete(String[] ids) throws ServiceException{
		if(ids.length>0){
			for(int index=0;index<ids.length;index++){
				delete(ids[index]);				
			}
		}
	}
	
	@Transactional(readOnly=true)
	public List<OrgUnit> findOrgTree(String parentCode) throws Exception {
		StringBuilder sb = new StringBuilder();
		/*
		 * ORACLE ONLY
		sb.append("select * from "+HibernateBeanHelper.getEntiryOfTable(OrgUnit.class)+" t where t.isdeleted=0  start with ");
		if(ExStringUtils.isNotEmpty(parentCode)){
			sb.append(" t.unitCode = '"+parentCode+"' ");
		}else{
			sb.append(" t.parentid is null ");
		}
		 
		sb.append( " connect by prior t.resourceid=t.parentid order siblings by t.unitLevel,t.showOrder");
		List<OrgUnit> list = jdbcDao.getBaseJdbcTemplate().findList(sb.toString(), OrgUnit.class, null);
		*/
		sb.append("select * from "+HibernateHelper.getEntiryOfTable(OrgUnit.class)+" t where t.isDeleted=0 ");
		if(ExStringUtils.isNotEmpty(parentCode)){
			sb.append(" and t.unitCode like '"+parentCode+"%'");
		}
		sb.append("  order by showOrder");
		return jdbcDao.getBaseJdbcTemplate().findList(sb.toString(), OrgUnit.class, null);
//		Map<String,Object> condition = new HashMap<String,Object>();
//		sb.append("from "+OrgUnit.class.getSimpleName()+" where isDeleted = :isDeleted ");
//		condition.put("isDeleted", 0);
//		//TODO 其他条件
//		sb.append(" order by showOrder ");
//		return (List<OrgUnit>)findByHql(sb.toString(),condition);
	}

	@Transactional(readOnly=true)
	public Page findOrgByCondition(Map<String, Object> condition, Page page) throws ServiceException{
		List<Criterion> objCriterion = new ArrayList<Criterion>();
		if(condition.containsKey("unitName")){//组织单位名称
			objCriterion.add(Restrictions.like("unitName","%"+condition.get("unitName")+"%"));
		}
		if (condition.containsKey("status")) {//状态
			objCriterion.add(Restrictions.eq("status", condition.get("status")));
		}		
		if (condition.containsKey("unitId")) {//ID
			if(condition.containsKey("isChild") && "y".equalsIgnoreCase(condition.get("isChild").toString())){
				objCriterion.add(Restrictions.eq("resourceid", condition.get("unitId")));
			}else {
				objCriterion.add(Restrictions.eq("parent.resourceid", condition.get("unitId")));
			//	objCriterion.add(Restrictions.or(Restrictions.eq("resourceid", condition.get("unitId")), Restrictions.eq("parent.resourceid", condition.get("unitId"))));
			}			
		}
		if(condition.containsKey("unitType")){//组织类型
			objCriterion.add(Restrictions.eq("unitType", condition.get("unitType")));
		}
		//Charles add
		objCriterion.add(Restrictions.gt("unitLevel", 0));
		objCriterion.add(Restrictions.eq("isDeleted", 0));//是否删除 =0
		return exGeneralHibernateDao.findByCriteria(OrgUnit.class,page,objCriterion.toArray(new Criterion[objCriterion.size()]));
	}


	/** 
	 * 通过 parentId 获取组织架构数据
	 * @param parentId			父节点id
	 * @param containSelf		数据中是否包含本身?
	 * @param containChildrenOrg数据中是否要进行递归查询?
	 * @return
	 * @throws ServiceException
	 */	
	@Transactional(readOnly=true)
	public List<OrgUnit> findOrgByParentId(String parentId, boolean containSelf, boolean containChildrenOrg) throws ServiceException{		
		@SuppressWarnings("unchecked")
		List<OrgUnit> all = (List<OrgUnit>)EhCacheManager.getCache(CacheSecManager.CACHE_SEC_ORGS).get(CacheSecManager.CACHE_SEC_ORGS);
		List<OrgUnit> result = getChildren(all, parentId, containChildrenOrg);
		if(containSelf) {
			result.add(getOrgUnitFromCache(parentId));
		}
		return result;
	}
	
	/**
	 * 从缓存中获取单位
	 * @param unitId
	 * @return
	 */
	public static OrgUnit getOrgUnitFromCache(String unitId) {		
		@SuppressWarnings("unchecked")
		List<OrgUnit> list = (List<OrgUnit>)EhCacheManager.getCache(CacheSecManager.CACHE_SEC_ORGS).get(CacheSecManager.CACHE_SEC_ORGS);
		if(null != list){
			for(OrgUnit orgUnit :list){
				if(unitId.equals(orgUnit.getResourceid())){
					return orgUnit;
				}
			}
		}
		return null;
	}
	
	public static void addOrgUnitToCache(OrgUnit orgUnit){
		@SuppressWarnings("unchecked")
		List<OrgUnit> list = (List<OrgUnit>)EhCacheManager.getCache(CacheSecManager.CACHE_SEC_ORGS).get(CacheSecManager.CACHE_SEC_ORGS);
		list.add(orgUnit);
	}
	
	public static void removeOrgUnitFromCache(Serializable orgUnitId){
		@SuppressWarnings("unchecked")
		List<OrgUnit> list = (List<OrgUnit>)EhCacheManager.getCache(CacheSecManager.CACHE_SEC_ORGS).get(CacheSecManager.CACHE_SEC_ORGS);
		if(null != list){
			for(OrgUnit org : list){
				if(orgUnitId.equals(org.getResourceid())){
					list.remove(org);					
					break;
				}
			}
		}
	}
	
	public static void updateOrgUnitToCache(OrgUnit orgUnit){
		@SuppressWarnings("unchecked")
		List<OrgUnit> list = (List<OrgUnit>)EhCacheManager.getCache(CacheSecManager.CACHE_SEC_ORGS).get(CacheSecManager.CACHE_SEC_ORGS);
		if(null != list){
			for(OrgUnit org : list){
				if(orgUnit.getResourceid().equals(org.getResourceid())){
					list.remove(org);
					list.add(orgUnit);
					break;
				}
			}
		}
	}
	
	/**
	 * 通过传入 所有的组织对象集合 以及  parentId 获取其子节点
	 * @param all		所有组织对象集合
	 * @param parentId	父节点id
	 * @param lists		可选参数,装结果的集合
	 * @return
	 */
	@Transactional(readOnly=true)
	public static List<OrgUnit> getChildren(List<OrgUnit> all, String parentId, boolean containChildrenOrg, List<OrgUnit>...lists) throws ServiceException {
		List<OrgUnit> result = lists.length > 0 ? lists[0] : new ArrayList<OrgUnit>();
		if(!StringUtils.isEmpty(parentId)) {
			for(OrgUnit o : all) {
				if(o.getParentId() != null && parentId.equalsIgnoreCase(o.getParentId())) {
					result.add(o);
					if(containChildrenOrg && hasChildren(all, parentId)) {
						result.addAll(getChildren(all, parentId, containChildrenOrg, lists));
					}
				}
			}
		}
		return result;
	}
	
	@Transactional(readOnly=true)
	public static boolean hasChildren(List<OrgUnit> all, String parentId) throws ServiceException{
		if(!StringUtils.isEmpty(parentId)) {
			for(OrgUnit o : all) {
				if(o.getParentId() != null && parentId.equalsIgnoreCase(o.getParentId())) {
					return true;
				}
			}
		}
		return false;
	}
	
	@Transactional(readOnly=true)
	public List<OrgUnit> findOrgUnitListByType(String unitType) throws ServiceException {
		Assert.hasText(unitType, "组织类型不能为空");		
		return findByHql("from "+OrgUnit.class.getSimpleName()+" where isDeleted = 0 and unitType = ? order by unitName ", unitType);
	}
	
	
	/**
	 * 获取所有子集（包括本身）
	 * @param parentId orgId
	 * @param includeSelf 是否包含本身
	 * @param includeChildren 是否包含儿子
	 * @return 
	 */
	@Transactional(readOnly=true)
	public List<?> getAllSubUnits(String parentId,boolean includeSelf,boolean includeChildren){
		List<Object> resultList =new ArrayList<Object>();
		OrgUnit org = (OrgUnit) exGeneralHibernateDao.get(OrgUnit.class, parentId);
		if(includeSelf){
			resultList.add(org);
		}
		if(!includeChildren){
			return resultList;
		}
		//递归拼凑子集
//		List<OrgUnit> allUnits =  (List<OrgUnit>)EhCacheManager.getCache(CacheSecManager.CACHE_SEC_ORGS).get(CacheSecManager.CACHE_SEC_ORGS);
		List<OrgUnit> allUnits =  (List<OrgUnit>)getAll(false);
		Map<String,Object> unitMap = new HashMap<String,Object>(allUnits.size());
		for(OrgUnit u:allUnits){
			unitMap.put(u.getResourceid(), u);
		}
//		Collection<Object> units = unitMap.values();
		Iterator<OrgUnit> it = allUnits.iterator();
		while(it.hasNext()){
			Object nextUnit = it.next();
			if(!resultList.contains(nextUnit)){
				boolean result = getAllChildren(unitMap, nextUnit, org.getResourceid(), resultList);
				if(result&&!resultList.contains(nextUnit)){
					//如果返回的是true，则说明它父类是正确的，所以当前类可以添加到realList中
					resultList.add(nextUnit);
				}
			}
		}
		return resultList;
	}

	/**
	 * 获取所有子集，不包括本身，供{@link #getAllSubUnits(Map, OrgUnit)}调用
	 * @param map 所有要被核对的对象，此处是所有org
	 * @param target 要核对的当前目标
	 * @param topId 顶级org的id
	 * @param resultList 最后返回的结果
	 * @return
	 */	
	private boolean getAllChildren(Map<String,Object> map,Object target,String topId,List<Object> resultList){
		//如果找不到这该类或者已经是顶级的类，则返回
		if(null == target || null ==((OrgUnit)target).getParent() || ((OrgUnit)target).getParent().getResourceid()==null){
			return false;
		}
		//如果其父类是要匹配的类，则返回true
		if(((OrgUnit)target).getParent().getResourceid().equals(topId)){
			return true;
		}
		
		boolean result =  getAllChildren(map, map.get(((OrgUnit)target).getParent().getResourceid()), topId,resultList);
		if(result&&!resultList.contains(target)){
			//如果返回的是true，则说明它父类是正确的，所以当前类可以添加到realList中
			resultList.add(target);
		}
		return result;
	}


}
